package io.gitee.chearnee.fw.sidecar.workshop;

import io.gitee.chearnee.fw.sidecar.client.ClientHelper;
import org.springframework.scheduling.concurrent.CustomizableThreadFactory;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * @author cn
 * @version 1.0
 * @description
 * @date 12/19/2022 2:35 PM
 */
public class ActionConsumer {
    private static final int DEFAULT_QUEUE_SIZE = 64;
    private static final double FACTOR = 0.75;
    private static final long DEFAULT_PERIOD = 500;
    private static final ScheduledExecutorService CONSUMER_POOL =
            Executors.newSingleThreadScheduledExecutor(new CustomizableThreadFactory("sidecar-consumer-"));
    private static final ArrayBlockingQueue<Object> CONSUMER_TASK_QUEUE = new ArrayBlockingQueue<>(DEFAULT_QUEUE_SIZE);
    private static volatile int taskCount = 0;
    private static final Object lock = new Object();

    private static ClientHelper clientHelper;

    public static void setClientHelper(ClientHelper clientHelper) {
        ActionConsumer.clientHelper = clientHelper;
    }

    public static void trigger() {
        triggerExec();
    }


    //region exec
    private static void execAfter() {
        CONSUMER_TASK_QUEUE.clear();
        taskCount = 0;
    }

    private static void triggerExec() {
        synchronized (lock) {
            if (++taskCount >= DEFAULT_QUEUE_SIZE * FACTOR) {
                exec();
            }
        }
        CONSUMER_TASK_QUEUE.add(WorkShop.take());
    }

    public static void timeExec() {
        CONSUMER_POOL.scheduleAtFixedRate(ActionConsumer::exec, 0, DEFAULT_PERIOD, TimeUnit.MILLISECONDS);
    }

    private static void exec() {
        Object[] objects = CONSUMER_TASK_QUEUE.toArray();
        synchronized (lock) {
            clientHelper.process(objects);
            execAfter();
        }
    }
    //endregion

}
